import { JwtService } from '@nestjs/jwt';
import {
    CanActivate,
    ExecutionContext,
    Inject,
    Injectable,
    UnauthorizedException,
} from '@nestjs/common';

import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
import { Request } from 'express';
import { Role } from './user/entities/role.entity';


declare module 'express' {
    //  手写的身份认证和 基于 passport 在request挂载了 user  所以扩展的user类型比较混乱
    interface Request {
        user: {
   
     
            roles: number[] | Role[],
            id:number ,
            token:string
        }
    }
}

@Injectable()
export class LoginGuard implements CanActivate {
    @Inject(JwtService)
    private jwtService: JwtService;

    @Inject()
    private reflector: Reflector;

    canActivate(
        context: ExecutionContext,
    ): boolean | Promise<boolean> | Observable<boolean> {
        
        const request: Request = context.switchToHttp().getRequest();

        // 获取 metadata 来判断是否需要登录：
        const requireLogin = this.reflector.getAllAndOverride('require-login', [
            context.getClass(),
            context.getHandler(),
        ]);
        
        // 没有被装饰器修饰的接口 全部可以通过校验
        if(!requireLogin){
            return true
        }

        const authorization = request.header('authorization') || '';

        const bearer = authorization.split(' ');

        if (!bearer || bearer.length < 2) {
            throw new UnauthorizedException('登录 token 错误');
        }

        const token = bearer[1];
        try {
            const info = this.jwtService.verify(token);
            request.user = info.user; // 将查询到的user信息 存到request 对象中  减少访问数据库次数 节省性能
            return true;
        } catch (e) {
            throw new UnauthorizedException('登录 token 失效，请重新登录');
        }
    }
}
